package com.ctl.utils;

import java.io.*;
import java.net.URI;
import java.net.URL;
import java.util.*;
import java.util.jar.JarFile;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import java.util.zip.ZipEntry;

import org.apache.commons.io.FileUtils;
import org.slf4j.*;
public class ConfigUtils {
	private static Properties config;
	private static InputStream is;
	static Logger logger = LoggerFactory.getLogger(ConfigUtils.class);

	public static String tmpPath = System.getProperty("java.io.tmpdir") + File.separator + "asset" + File.separator;
	public static boolean jarRun = false;
	public static String SPRINGBOOT_CLASSES_ = "BOOT-INF/classes!/";
	public static String SPRINGBOOT_CLASSES = "BOOT-INF/classes/";

	/**
	 * @param jarFile  jar包全路径
	 * @param filePath jar包中路径
	 * @return
	 */
	public static Stream<Map.Entry<ZipEntry, InputStream>> readJarFile(JarFile jarFile, String filePath) {
		Stream<Map.Entry<ZipEntry, InputStream>> readingStream = jarFile.stream().filter(entry -> !entry.isDirectory() && entry.getName().equals(filePath))
				.map(entry -> {
					try {
						return new AbstractMap.SimpleEntry<>(entry, jarFile.getInputStream(entry));
					} catch (IOException e) {
						return new AbstractMap.SimpleEntry<>(entry, null);
					}
				});
		return readingStream.onClose(() -> {
			try {
				jarFile.close();
			} catch (IOException e) {
				System.err.println(e);
			}
		});
	}

	/**
	 * 复制jar包中的资源文件到指定目录
	 *
	 * @param path     jar包所在路径  /root/test.jar
	 * @param tempPath 保存目录      /tmp
	 * @param filePath 需要进行复制的资源文件目录：以classes/开头   classes/application.properties(test.jar!classes/application.properties)
	 *                 BOOT-INF/classes/application.properties(springboot-call-spark-application-0.0.1-SNAPSHOT.jar!BOOT-INF/classes/application.properties)
	 */
	public static void copyJarResourcesFileToTemp(URI path, String tempPath, String filePath) {
		try {
			List<Map.Entry<ZipEntry, InputStream>> collect = readJarFile(new JarFile(path.getPath()), filePath).collect(Collectors.toList());
			for (Map.Entry<ZipEntry, InputStream> entry : collect) {
				// 文件相对路径
				String key = entry.getKey().getName();
				// 文件流
				InputStream stream = entry.getValue();
				File newFile = new File(tempPath + key.replaceAll("BOOT-INF/classes", "").replaceAll("classes", ""));
				if (!newFile.getParentFile().exists()) {
					newFile.getParentFile().mkdirs();
				}
				FileUtils.copyToFile(stream, newFile);
//                FileUtil.writeFromStream(stream, newFile);
			}
		} catch (IOException e) {
			System.err.println(e);
		}
	}

	static {
		URL url = ConfigUtils.class.getResource("");
		String protocol = url.getProtocol();
		logger.info("url={},protocol={},path={}", url, protocol, url.getPath());
		String path = ConfigUtils.class.getResource("/application.properties").getPath();
		logger.info("path={}", url.getPath());
		if ("jar".equals(protocol)) {
			try {
				path = url.getPath();
				jarRun = true;
				logger.info("jarRun={}", jarRun);
				if (path.contains(SPRINGBOOT_CLASSES_)) {
					copyJarResourcesFileToTemp(new URI(path.split("!")[0]), tmpPath, SPRINGBOOT_CLASSES + "application.properties");
				} else {
					copyJarResourcesFileToTemp(new URI(path.split("!")[0]), tmpPath, "application.properties");
				}
				path = tmpPath + "application.properties";
			} catch (Exception e) {
				logger.error("", e);
			}
		}
		config = new Properties();
//        is = ConfigUtils.class.getClassLoader().getResourceAsStream("application.properties");
		try {
			is = new FileInputStream(path);
		} catch (FileNotFoundException e) {
			logger.error("", e);
		}
		try {
			config.load(is);
			System.out.println(config);
			is.close();
		} catch (Exception e) {
			logger.error("初始化资源文件失败:", e);
		} finally {

		}
	}
	public static boolean flushProperties(){
		is = ConfigUtils.class.getClassLoader().getResourceAsStream("config.properties");
		try {
			config.load(is);
			is.close();
			return true;
		} catch (IOException e) {
			logger.error("初始化资源文件失败:",e);
		}finally{
			
		}
		return false;
	}
	public static String getType(String type) {
		return config.getProperty(type);
	}

	/**
	 * @return \u8FD4\u56DE\u6240\u6709\u7684key\u548Cvalue
	 * @deprecated \u8FD4\u56DE\u7684\u7C7B\u578B\u662FHashMap<String,String>
	 */
	public static HashMap<String, String> getProperties() {
		HashMap<String, String> map = new HashMap<String, String>();
		Set<Object> set = new HashSet<Object>();
		set = config.keySet();
		Iterator<Object> iter = set.iterator();
		String key;
		for (; iter.hasNext();) {
			key = iter.next().toString();
			map.put(key, ConfigUtils.getType(key));
		}
		return map;
	}

	/**
	 * @deprecated \u8FD4\u56DE\u7C7B\u578B\u662F HashSet
	 *             \u6240\u6709\u7684\u8BE5\u8D44\u6E90\u6587\u4EF6\u4E2D\u6240\u6709\u7684key
	 *             (Object)
	 */
	public static Set<Object> getAllKeys() {
		Set<Object> set = new HashSet<Object>();
		set = config.keySet();
		return set;
	}

	/**
	 * @deprecated \u8FD4\u56DE\u7C7B\u578B\u662F HashSet
	 *             \u6240\u6709\u7684\u8BE5\u8D44\u6E90\u6587\u4EF6\u4E2D\u6240\u6709\u7684value
	 *             (Object)
	 */
	public static Set<Object> getAllValues() {
		Set<Object> set = new HashSet<Object>();
		Set<Object> setReturtn = new HashSet<Object>();
		set = config.keySet();
		Iterator<Object> iter = set.iterator();
		String key;
		for (; iter.hasNext();) {
			key = iter.next().toString();
			setReturtn.add(ConfigUtils.getType(key));
		}
		return setReturtn;
	}

	/**
	 * @param key
	 *            \u8981\u5224\u65AD\u7684key
	 * @return \u5B58\u5728\u8FD4\u56DEtrue\u4E0D\u5B58\u5728\u8FD4\u56DEfalse
	 */
	public static boolean containKey(String key) {
		return ConfigUtils.getAllKeys().contains(key);
	}

	private static Properties getConfig() {
		return config;
	}
	public static void main(String[] args) {
		String name=getType("name");
		logger.info(name);
		logger.info(getType("age"));
	}
}
